home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / a86b.arc / EFFADDR.DOC < prev    next >
Text File  |  1986-06-22  |  13KB  |  230 lines

  1. ---EFFADDR.DOC---
  2.  
  3. Effective Addresses
  4.  
  5. Most memory data accessing in the 86 family is accomplished via the mechanism of
  6. the effective address.  Wherever an effective address specifier "eb", "ew" or
  7. "ed" appears in the list of 8086 instructions, you may use a wide variety of
  8. actual operands in that instruction.  These include general registers, memory
  9. variables, and a variety of indexed memory quantities.
  10.  
  11. GENERAL REGISTERS: Wherever an "ew" appears, you can use any of the 16-bit
  12.    registers AX,BX,CX,DX,SI,DI,SP, or BP.  Wherever an "eb" appears, you can
  13.    use any of the 8-bit registers AL,BL,CL,DL,AH,BH,CH, or DH.  For example,
  14.    the "ADD ew,rw" form subsumes the 16-bit register-to-register adds; for
  15.    example, ADD AX,BX; ADD SI,BP; ADD SP,AX.
  16.  
  17. MEMORY VARIABLES: Wherever an "ew" appears, you can use a word-memory-variable.
  18.    Wherever an "eb" appears, you can use a byte-memory-variable.  Variables are
  19.    typically declared in the DATA segment, using a DW declaration for a word-
  20.    variable, or a DB declaration for a byte-variable.  For example, you can
  21.    declare variables:
  22.         DATA_PTR  DW ?
  23.         ESC_CHAR  DB ?
  24.  
  25.    Later, you can load or store these variables:
  26.         MOV SI,DATA_PTR    ; load DATA_PTR into SI for use
  27.         LODSW              ; fetch the word pointed to by DATA_PTR
  28.         MOV DATA_PTR,SI    ; store the value incremented by the LODSW
  29.         MOV BL,ESC_CHAR    ; load the byte-variable ESC_CHAR
  30.  
  31.    Alternatively, you can address specific unnamed memory locations by enclosing
  32.    the location value in square barckets; for example,
  33.         MOV AL,[02000]     ; load contents of location 02000 into AL
  34.  
  35.    Note that A86 discerned from context (loading into AL) that a BYTE at 02000
  36.    was intended.  Sometimes this is impossible, and you must speicify byte or
  37.    word:
  38.         INC B[02000]       ; increment the byte at location 02000
  39.         MOV W[02000],0     ; set the WORD at location 02000 to zero
  40.  
  41. INDEXED MEMORY: The 86 supports the use of certain registers as base pointers
  42.    and index registers into memory.  BX and BP are the base registers; SI and DI
  43.    are the index registers.  You may combine at most one base register, at most
  44.    one index register, and a constant number into a run-time pointer that
  45.    determines the location of the effective address memory to be used in the
  46.    instruction.  These can be given explicitly, by enclosing the index registers
  47.    in brackets:
  48.         MOV AX,[BX]
  49.         MOV CX,W[SI+17]
  50.         MOV AX,[BX+BP+5]
  51.         MOV AX,[BX][BP]5   ; another way to write the same instruction
  52.  
  53.    Or, indexing can be accomplished by declaring variables in a based structure:
  54.         STRUC [BP]         ; NOTE based structures are unique to A86!
  55.           BP_SAVE   DW ?
  56.           RET_ADDR  DW ?
  57.           PARM1     DW ?
  58.           PARM2     DW ?
  59.         ENDS
  60.         INC PARM1         ; equivalent to INC W[BP+4]
  61.  
  62.     Finally, indexing can be done by mixing explicit components with declared
  63.     ones:
  64.         TABLE    DB  4,2,1,3,5
  65.         MOV AL,TABLE[BX]
  66.  
  67.  
  68. Segmentation and Effective Addresses
  69.  
  70. The 86 family has four segment registers, CS, DS, ES, and SS, used to address
  71. memory.  Each segment register points to 64K bytes of memory within the 1-
  72. megabyte memory space of the 86.  (The start of the 64K is calculated by
  73. multiplying the segment register value by 16; i.e., by shifting the value
  74. left by one hex digit.)  If your program's code, data and stack areas can
  75. all fit in the same 64K bytes, you can leave all the segment registers set to
  76. the same value.  In that case, you won't have to think about segment registers--
  77. no matter which one is used to address memory, you'll still get the same 64K.
  78. If your program needs more than 64K, you must point one or more segment
  79. registers to other parts of the memory space.  In this case, you must take
  80. care that your memory references use the segment registers you intended.
  81.  
  82. Each effective address memory access has a defualt segment register, to be used
  83. if you do not explicitly specify which segment register you wish.  For most
  84. effective addresses, the default segment register is DS.  The exceptions are
  85. those effective addresses that use the BP register for indexing.  All BP-indexed
  86. memory references have a default of SS.  (This is becuase BP is intended to be
  87. used for addressing local variables, stored on the stack.)
  88.  
  89. If you wish your memory access to use a different segment register, you provide
  90. a segment-override byte before the instruction containing the effective
  91. address operand.  In the A86 language, you code the override by giving the
  92. name of the segment register you wish before the instruction mnemonic.  For
  93. example, suppose you want to load the AL register with the memory byte pointed
  94. to by BX.  If you code MOV AL,[BX], the DS register will be used to determine
  95. which 64K segment BX is pointing to.  If you want the byte to come from the
  96. CS-segment instead, you code CS MOV AL,[BX].  Be aware that the segment-override
  97. byte has effect only upon the single instruction that follows it.  If you have
  98. a sequence of instructions requiring overrides, you must give an override byte
  99. before every instruction in the sequence.  (In that case, you may wish to
  100. consider changing the value of the default segment register for the duration of
  101. the sequence.)
  102.  
  103. NOTE: This method for providing segment-overrides is unique to the A86
  104. assembler!  The assemblers provided by Intel and IBM (MS-DOS) attempt to figure
  105. out segment allocation for you, and plug in segment-override bytes "behind your
  106. back".  In order to do this, those assemblers require you to inform them which
  107. variables and structures are pointed to by which segment registers.  That is
  108. what the ASSUME directive in those assemblers is all about.  I wrote Intel's
  109. first 86 assembler, ASM86, so I have been watching the situation since day one.
  110. Over the years, I have concluded that the ASSUME-mechanism creates far, far
  111. more confusion that it solves.  So I scrapped it; and the result is an assembler
  112. with far less red tape.  But if your program needs more than 64K, you do have
  113. to manage those segment registers yourself; so take care!
  114.  
  115.  
  116. Effective Use of Effective Addresses
  117.  
  118. Remember that all of the common instructions of the 86 family allow effective
  119. addresses as operands.  (The only major functions that don't are the AL/AX
  120. specific ones: multiply, divide, and input/output).  This means that you don't
  121. have to funnel many through AL or AX just to do something with them.  You can
  122. perform all the common arithmetic, PUSH/POP, and MOVes from any general
  123. register to any general register; from any memory location (indexed if you
  124. like) to any register; and (this is most often overlooked) from any register TO
  125. memory.  The only thing you can't do in general is memory-to-memory.  Among the
  126. more common operations that inexperienced 86 programmers overlook are:
  127.  
  128.    * setting memory variables to immediate values
  129.    * testing memory variables, and comparing them to constants
  130.    * preserving memory variables by PUSHing and POPping them
  131.    * incrementing and decrementing memory variables
  132.    * adding into memory variables
  133.  
  134.  
  135. Encoding of Effective Addresses
  136.  
  137. Unless you are concerned with the nitty-gritty details of 86 instruction
  138. encoding, you don't need to read this section.
  139.  
  140. Every instruction with an effective address has an encoded byte, known as the
  141. effective address byte, following the 1-byte opcode for the instruction. (For
  142. obscure reasons, Intel calls this byte the ModRM byte.)  If the effective
  143. address is a memory variable, or an indexed memory location with a non-zero
  144. constant offset, then the effective address byte will be immediately followed
  145. by the offset amount.  Amounts in the range -128 to +127 are given by a single
  146. signed byte, denoted by "D8" in the table below.  Amounts requiring a 2-byte
  147. representation are denoted by "D16" in the table below.  As with all 16-bit
  148. memory quantities in the 86 family, the word is stored with the least
  149. significant byte FIRST.
  150.  
  151. The following table of effective address byte values is organized into 32
  152. rows and 8 columns.  The 32 rows give the possible values for the effective
  153. address operand: 8 registers and 24 memory indexing modes.  A 25th indexing
  154. mode, [BP] with zero displacement, has been pre-empted by the simple-memory-
  155. variable case.  If you code [BP] with no displacement, you will get [BP]+D8,
  156. with a D8-value of zero.
  157.  
  158. The 8 columns of the table reflect further information given by the effective
  159. address byte.  Usually, this is the identity of the other (always a register)
  160. operand of a 2-operand instruction.  Those instructions are identified by a
  161. "/r" following the opcode byte in the instruction list.  Sometimes, the
  162. information given supplements the opcode byte in identifying the instruction
  163. itself.  Those instructions are identified by a "/" followed by a digit from
  164. 0 through 7.  The digit tells which of the 8 columns you should use to find
  165. the effective address byte.
  166.  
  167. For example, suppose you have a perverse wish to know the precise bytes
  168. encoded by the instruction SUB B[BX+17],100.  This instruction subtracts an
  169. immediate quantity, 100, from an effective address quantity, B[BX+17].  By
  170. consulting the instruction list, you find the general form SUB eb,ib.  The
  171. opcode bytes given there are 80 /5 ib.  The "/5" denotes an effective-address
  172. byte, whose value will be taken from column 5 of the table below.  The offset
  173. 17 decimal, which is 11 hex, will fit in a single "D8" byte, so we take our
  174. value from the "[BX] + D8" row.  The table tells us that the effective
  175. address byte is 6F.  Immediately following the 6F is the offset, 11 hex.
  176. Following that is the ib-value of 100 decimal, which is 64 hex.  So the bytes
  177. generated by SUB B[BX+17],100 are 80 6F 11 64.
  178.  
  179.  
  180. Table of Effective Address byte values
  181.  
  182. s  =    ES   CS   SS   DS
  183. rb =    AL   CL   DL   BL   AH   CH   DH   BH
  184. rw =    AX   CX   DX   BX   SP   BP   SI   DI
  185. digit=   0    1    2    3    4    5    6    7
  186.                                                Effective
  187. EA byte                                         address:
  188. values: 00   08   10   18   20   28   30   38    [BX + SI]
  189.         01   09   11   19   21   29   31   39    [BX + DI]
  190.         02   0A   12   1A   22   2A   32   3A    [BP + SI]
  191.         03   0B   13   1B   23   2B   33   3B    [BP + DI]
  192.         04   0C   14   1C   24   2C   34   3C    [SI]
  193.         05   0D   15   1D   25   2D   35   3D    [DI]
  194.         06   0E   16   1E   26   2E   36   3E    D16 (simple var)
  195.         07   0F   17   1F   27   2F   37   3F    [BX]
  196.         40   48   50   58   60   68   70   78    [BX + SI] + D8
  197.         41   49   51   59   61   69   71   79    [BX + DI] + D8
  198.         42   4A   52   5A   62   6A   72   7A    [BP + SI] + D8
  199.         43   4B   53   5B   63   6B   73   7B    [BP + DI] + D8
  200.         44   4C   54   5C   64   6C   74   7C    [SI] + D8
  201.         45   4D   55   5D   65   6D   75   7D    [DI] + D8
  202.         46   4E   56   5E   66   6E   76   7E    [BP] + D8
  203.         47   4F   57   5F   67   6F   77   7F    [BX] + D8
  204.         80   88   90   98   A0   A8   B0   B8    [BX + SI] + D16
  205.         81   89   91   99   A1   A9   B1   B9    [BX + DI] + D16
  206.         82   8A   92   9A   A2   AA   B2   BA    [BP + SI] + D16
  207.         83   8B   93   9B   A3   AB   B3   BB    [BP + DI] + D16
  208.         84   8C   94   9C   A4   AC   B4   BC    [SI] + D16
  209.         85   8D   95   9D   A5   AD   B5   BD    [DI] + D16
  210.         86   8E   96   9E   A6   AE   B6   BE    [BP] + D16
  211.         87   8F   97   9F   A7   AF   B7   BF    [BX] + D16
  212.         C0   C8   D0   D8   E0   E8   F0   F8    ew=AX   eb=AL
  213.         C1   C9   D1   D9   E1   E9   F1   F9    ew=CX   eb=CL
  214.         C2   CA   D2   DA   E2   EA   F2   FA    ew=DX   eb=DL
  215.         C3   CB   D3   DB   E3   EB   F3   FB    ew=BX   eb=BL
  216.         C4   CC   D4   DC   E4   EC   F4   FC    ew=SP   eb=AH
  217.         C5   CD   D5   DD   E5   ED   F5   FD    ew=BP   eb=CH
  218.         C6   CE   D6   DE   E6   EE   F6   FE    ew=SI   eb=DH
  219.         C7   CF   D7   DF   E7   EF   F7   FF    ew=DI   eb=BH
  220.  
  221. D8 denotes an 8-bit displacement following the EA byte,
  222. to be sign-extended and added to the index.
  223.  
  224. D16 denotes a 16-bit displacement following the EA byte,
  225. to be added to the index.
  226.  
  227. Default segment register is SS for effective addresses containing
  228. a BP index; DS for other memory effective addresses.
  229.  
  230.